/*
 * Copyright 2019 Flipkart Internet Pvt. Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.flipkart.ohos.proteus.managers;

import ohos.agp.components.Component;

import com.flipkart.ohos.proteus.BoundAttribute;
import com.flipkart.ohos.proteus.DataContext;
import com.flipkart.ohos.proteus.ProteusContext;
import com.flipkart.ohos.proteus.ProteusView;
import com.flipkart.ohos.proteus.ViewTypeParser;
import com.flipkart.ohos.proteus.value.Layout;
import com.flipkart.ohos.proteus.value.ObjectValue;

import java.util.ArrayList;
import java.util.List;

/**
 * ViewManager
 *
 * @author aditya.sharat
 */
public class ViewManager implements ProteusView.Manager {
    protected final ProteusContext context;

    protected final Component view;

    protected final Layout layout;

    protected final DataContext dataContext;

    protected final ViewTypeParser parser;

    protected final List<BoundAttribute> boundAttributes;

    protected Object extras;

    public ViewManager(ProteusContext context, ViewTypeParser parser,
                       Component view, Layout layout, DataContext dataContext) {
        this.context = context;
        this.parser = parser;
        this.view = view;
        this.layout = layout;
        this.dataContext = dataContext;

        if (layout.attributes != null) {
            List<BoundAttribute> boundAttributeList = new ArrayList<>();
            for (Layout.Attribute attribute : layout.attributes) {
                if (attribute.value.isBinding()) {
                    boundAttributeList.add(new BoundAttribute(attribute.id, attribute.value.getAsBinding()));
                }
            }
            if (boundAttributeList.size() > 0) {
                this.boundAttributes = boundAttributeList;
            } else {
                this.boundAttributes = null;
            }
        } else {
            this.boundAttributes = null;
        }
    }

    @Override
    public void update(ObjectValue data) {
        // update the data context so all child views can refer to new data
        if (data != null) {
            updateDataContext(data);
        }

        // update the bound attributes of this view
        if (this.boundAttributes != null) {
            for (BoundAttribute boundAttribute : this.boundAttributes) {
                this.handleBinding(boundAttribute);
            }
        }
    }

    @Override
    public Component findViewById(String id) {
        return view.findComponentById(context.getInflater().getUniqueViewId(id));
    }

    @Override
    public ProteusContext getContext() {
        return this.context;
    }

    @Override
    public Layout getLayout() {
        return this.layout;
    }

    public DataContext getDataContext() {
        return dataContext;
    }

    @Override
    public Object getExtras() {
        return this.extras;
    }

    @Override
    public void setExtras(Object extras) {
        this.extras = extras;
    }

    private void updateDataContext(ObjectValue data) {
        if (dataContext.hasOwnProperties()) {
            dataContext.update(context, data);
        } else {
            dataContext.setData(data);
        }
    }

    private void handleBinding(BoundAttribute boundAttribute) {
        //noinspection unchecked
        parser.handleAttribute(view, boundAttribute.attributeId, boundAttribute.binding);
    }
}
